home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * CursorUtilities.c - cursor stuff- spinning watch, etc
- *
- * 26/9/94 ©1994, Graham Cox
- *
- * This code based on "Macintosh Programming Secrets" 2nd Edition by Keith Rollin & Scott K
- *
- *************************************************************************************************/
-
- #include "CursorUtilities.h"
-
- #include <LowMem.h>
-
- short gVBLCount;
- VBLTaskWithA5Ptr gCursorTask = NULL;
-
- acurHdl gWatchSpinner = NULL;
- acurHdl gBallSpinner = NULL;
-
- // macro for doing dodgy 68000 stuff!
-
- #ifndef __powerc
- VBLTaskWithA5Ptr GetVBLRec(void) = 0x2008;
- #endif
-
- static Handle GetDetachedResource(ResType aType, short anID);
-
- /*-------------------------*** GETDETACHEDRESOURCE ***--------------------------------*/
- /*
-
- returns a detched resourse with type and ID passed.
-
- ----------------------------------------------------------------------------------------*/
-
- static Handle GetDetachedResource(ResType aType, short anID)
- {
- Handle temp = NULL;
-
- temp = GetResource(aType,anID);
-
- if (temp)
- DetachResource(temp);
-
- return temp;
- }
-
- /*--------------------------*** INITANIMATEDCURSOR ***--------------------------------*/
- /*
-
- sets up an animated cursor by reading the 'acur' resource with the ID passed.
-
- ----------------------------------------------------------------------------------------*/
-
- acurHdl InitAnimatedCursor(short resID)
- {
- acurHdl temp;
- short ccount;
- CursHandle aCursor;
- CursHandle* workPtr;
-
- temp = (acurHdl) GetDetachedResource('acur',resID);
-
- if (temp)
- {
- ccount = (*temp)->numCursors;
- (*temp)->numCursors *= 32;
- (*temp)->index = 0;
-
- HLock((Handle) temp);
- workPtr = (*temp)->cursors;
-
- while(ccount--)
- {
- aCursor = (CursHandle) GetDetachedResource('CURS',*(short*) workPtr);
- *workPtr++ = aCursor;
- }
- HUnlock((Handle) temp);
- }
- return(temp);
- }
-
-
-
- /*-------------------------*** STARTCURSORANIMATION ***-------------------------------*/
- /*
- sets up the VBL queue to animate the cursor passed.
-
- ----------------------------------------------------------------------------------------*/
-
- void StartCursorAnimation(short period, acurHdl theCursor)
- {
- // primes the VBL queue to spin the cursor automatically
-
- VBLUPP vTaskUPP;
-
- if (theCursor)
- {
- LockCursorData(theCursor);
-
- gVBLCount = period;
- gCursorTask = (VBLTaskWithA5Ptr) NewPtr(sizeof(VBLTaskWithA5));
-
- gCursorTask->theTask.qType = vType;
-
- vTaskUPP = NewVBLProc((ProcPtr) VBLCursorSpin);
-
- gCursorTask->theTask.vblAddr = vTaskUPP;
- gCursorTask->theTask.vblCount = period;
- gCursorTask->theTask.vblPhase = 0;
- gCursorTask->A5 = (long) LMGetCurrentA5();
- gCursorTask->theCursor = theCursor;
-
- (void) VInstall((QElemPtr) gCursorTask);
- }
- }
-
-
- /*-------------------------*** STOPCURSORANIMATION ***--------------------------------*/
- /*
-
- Kills the current cursor in the VBL queue and unlocks it. This then restores the arrow.
- ----------------------------------------------------------------------------------------*/
-
- void StopCursorAnimation(void)
- {
- // removes spinning cursor task from the VBL queue
-
- acurHdl theCursor;
-
- if (gCursorTask)
- {
- (void) VRemove((QElemPtr) gCursorTask);
-
- theCursor = gCursorTask->theCursor;
- DisposeRoutineDescriptor(gCursorTask->theTask.vblAddr);
-
- DisposePtr((Ptr) gCursorTask);
- gCursorTask = NULL;
- UnlockCursorData(theCursor);
-
- SetCursor( &qd.arrow );
- }
- }
-
-
- /*-----------------------------*** ANIMATECURSOR ***----------------------------------*/
- /*
-
- Can be called repeatedly to animate a cursor. However, it is simpler to let the VBL task
- do this in general.
-
- ----------------------------------------------------------------------------------------*/
-
- void AnimateCursor(short increment,acurHdl theCursor)
- {
- // used only for non-VBL cursor spinning
-
- short oldIndex,newIndex;
- CursHandle aCursor;
-
- if (theCursor)
- {
- oldIndex = (*theCursor)->index / 32;
-
- (*theCursor)->index += increment;
- (*theCursor)->index %= (*theCursor)->numCursors;
-
- newIndex = (*theCursor)->index / 32;
-
- if (newIndex != oldIndex)
- {
- aCursor = (*theCursor)->cursors[newIndex];
- SetCursor(*aCursor);
- }
- }
- }
-
-
- /*----------------------------*** LOCKCURSORDATA ***----------------------------------*/
- /*
-
- locks down the cursor handles ready for animation
-
- ----------------------------------------------------------------------------------------*/
-
- void LockCursorData(acurHdl theCursor)
- {
- // locks the cursor and its internal data
-
- short ccount;
- CursHandle *workPtr;
-
- ccount = (*theCursor)->numCursors / 32;
-
- HLockHi((Handle) theCursor);
- workPtr = (*theCursor)->cursors;
-
- while (ccount--)
- HLockHi((Handle) *workPtr++);
- }
-
-
- /*--------------------------*** UNLOCKCURSORDATA ***----------------------------------*/
- /*
-
- unlocks the cursor handles
- ----------------------------------------------------------------------------------------*/
-
- void UnlockCursorData(acurHdl theCursor)
- {
- // unlocks the cursor
-
- short ccount;
- CursHandle *workPtr;
-
- ccount = (*theCursor)->numCursors / 32;
- workPtr = (*theCursor)->cursors;
-
- while (ccount--)
- HUnlock((Handle) *workPtr++);
-
- HUnlock((Handle) theCursor);
- }
-
- /*-----------------------------*** VBLCURSORSPIN ***----------------------------------*/
- /*
-
- this is the VBL callback that actually performs the animation of a VBL-driven cursor
- ----------------------------------------------------------------------------------------*/
-
- #ifndef __powerc
- void VBLCursorSpin()
- #else
- void VBLCursorSpin(VBLTaskWithA5Ptr theTask)
- #endif
- {
- // this is the function that is called from the interrupt task.
-
- acurHdl theCrsr;
- long oldA5;
-
- #ifndef __powerc
- VBLTaskWithA5Ptr theTask;
-
- theTask = GetVBLRec();
- oldA5 = SetA5(theTask->A5);
- if (LMGetCrsrBusy() == 0)
- {
- theCrsr = theTask->theCursor;
- AnimateCursor(32,theCrsr);
- }
- theTask->theTask.vblCount = gVBLCount;
- (void) SetA5(oldA5);
-
- #else
- oldA5 = SetA5(theTask->A5);
-
- if (LMGetCrsrBusy() == 0)
- {
- theCrsr = theTask->theCursor;
- AnimateCursor(32,theCrsr);
- }
- theTask->theTask.vblCount = gVBLCount;
- (void) SetA5(oldA5);
- #endif
- }
-
-
- /*-----------------------------*** SETWATCHCURSOR ***---------------------------------*/
- /*
-
- starts the animated watch cursor. To stop it, call StopCursorAnimation.
- ----------------------------------------------------------------------------------------*/
-
- void SetWatchCursor()
- {
- // HL call installs VBL spinner for watch, which should have been inited beforehand
-
- if (gWatchSpinner && ! gCursorTask)
- StartCursorAnimation(8, gWatchSpinner);
- }
-
- /*---------------------------*** SETBEACHBALLCURSOR ***-------------------------------*/
- /*
-
- starts the animated "beachball" cursor. To stop it, call StopCursorAnimation.
- ----------------------------------------------------------------------------------------*/
-
- void SetBeachBallCursor()
- {
- if (gBallSpinner && ! gCursorTask)
- StartCursorAnimation(4, gBallSpinner);
-
- }
-
- /*-------------------------------*** GETMODIFIERS ***---------------------------------*/
- /*
-
- can be called at any time to get the current state of the keyboard modifier keys. Useful
- if the cursor is changed with different modifiers down.
- ----------------------------------------------------------------------------------------*/
-
- short GetModifiers()
- {
- // returns the current state of the modifier keys as if it was the modifier field in
- // an event record. This can be called at any time, even when an event is not available.
- // It is very useful for updating the cursor to show the modifier state.
-
- unsigned char theKeys[16];
- short modifiers;
-
-
- GetKeys((UInt32*) theKeys);
-
- modifiers = 0;
-
- ((theKeys[0x37 >> 3] >> (0x37 & 7)) & 1)? modifiers |= cmdKey : 0;
- ((theKeys[0x38 >> 3] >> (0x38 & 7)) & 1)? modifiers |= shiftKey : 0;
- ((theKeys[0x39 >> 3] >> (0x39 & 7)) & 1)? modifiers |= alphaLock : 0;
- ((theKeys[0x3A >> 3] >> (0x3A & 7)) & 1)? modifiers |= optionKey : 0;
- ((theKeys[0x3B >> 3] >> (0x3B & 7)) & 1)? modifiers |= controlKey : 0;
-
- (! Button())? modifiers |= btnState : 0;
-
- return modifiers;
- }
-
-
- /*------------------------------*** APPCURSORINIT ***---------------------------------*/
- /*
- high-level call to initialise the two animated cursors. Extend this for others you may have
- ----------------------------------------------------------------------------------------*/
-
- void AppCursorInit()
- {
- // called once at application start-up to initialise the animated cursor globals.
-
- gWatchSpinner = InitAnimatedCursor(kWatchResID);
- gBallSpinner = InitAnimatedCursor(kBeachBallResID);
- }
-
- /*------------------------------*** CURSORANIMATING ***-------------------------------*/
- /*
- returns TRUE if an animated cursor is on screen. You should not call
- SetCursor if this is true, or ugly cursor flickering occurs.
- ----------------------------------------------------------------------------------------*/
-
- Boolean CursorAnimating()
- {
- return (gCursorTask != NULL);
- }
-